home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 2 / AACD 2.iso / AACD / Programming / fpc / compiler / cgi386ad.inc < prev    next >
Text File  |  1998-09-24  |  58KB  |  1,287 lines

  1. {
  2.     $Id: cgi386ad.inc,v 1.2.2.1 1998/04/08 11:38:43 peter Exp $
  3.     Copyright (c) 1993-98 by Florian Klaempfl
  4.  
  5.     This include file generates i386+ assembler from the parse tree
  6.  
  7.     This program is free software; you can redistribute it and/or modify
  8.     it under the terms of the GNU General Public License as published by
  9.     the Free Software Foundation; either version 2 of the License, or
  10.     (at your option) any later version.
  11.  
  12.     This program is distributed in the hope that it will be useful,
  13.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.     GNU General Public License for more details.
  16.  
  17.     You should have received a copy of the GNU General Public License
  18.     along with this program; if not, write to the Free Software
  19.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  
  21.  ****************************************************************************
  22. }
  23.  
  24.     procedure secondas(var p : ptree);
  25.  
  26.       var
  27.          pushed : tpushed;
  28.  
  29.       begin
  30.          secondpass(p^.left);
  31.          { save all used registers }
  32.          pushusedregisters(pushed,$ff);
  33.  
  34.          { push instance to check: }
  35.          case p^.left^.location.loc of
  36.             LOC_REGISTER,LOC_CREGISTER:
  37.               exprasmlist^.concat(new(pai386,op_reg(A_PUSH,
  38.                 S_L,p^.left^.location.register)));
  39.             LOC_MEM,LOC_REFERENCE:
  40.               exprasmlist^.concat(new(pai386,op_ref(A_PUSH,
  41.                 S_L,newreference(p^.left^.location.reference))));
  42.             else internalerror(100);
  43.          end;
  44.  
  45.          { we doesn't modifiy the left side, we check only the type }
  46.          set_location(p^.location,p^.left^.location);
  47.  
  48.          { generate type checking }
  49.          secondpass(p^.right);
  50.          case p^.right^.location.loc of
  51.             LOC_REGISTER,LOC_CREGISTER:
  52.               begin
  53.                  exprasmlist^.concat(new(pai386,op_reg(A_PUSH,
  54.                    S_L,p^.right^.location.register)));
  55.                  ungetregister32(p^.right^.location.register);
  56.               end;
  57.             LOC_MEM,LOC_REFERENCE:
  58.               begin
  59.                  exprasmlist^.concat(new(pai386,op_ref(A_PUSH,
  60.                    S_L,newreference(p^.right^.location.reference))));
  61.                  del_reference(p^.right^.location.reference);
  62.               end;
  63.             else internalerror(100);
  64.          end;
  65.          emitcall('DO_AS',true);
  66.          { restore register, this restores automatically the }
  67.          { result                                            }
  68.          popusedregisters(pushed);
  69.       end;
  70.  
  71.     procedure secondloadvmt(var p : ptree);
  72.  
  73.       begin
  74.          p^.location.register:=getregister32;
  75.          exprasmlist^.concat(new(pai386,op_csymbol_reg(A_MOV,
  76.             S_L,newcsymbol(pobjectdef(pclassrefdef(p^.resulttype)^.definition)^.vmt_mangledname,0),
  77.             p^.location.register)));
  78.       end;
  79.  
  80.     procedure secondis(var p : ptree);
  81.  
  82.       var
  83.          pushed : tpushed;
  84.  
  85.       begin
  86.          { save all used registers }
  87.          pushusedregisters(pushed,$ff);
  88.          secondpass(p^.left);
  89.          p^.location.loc:=LOC_FLAGS;
  90.          p^.location.resflags:=F_NE;
  91.  
  92.          { push instance to check: }
  93.          case p^.left^.location.loc of
  94.             LOC_REGISTER,LOC_CREGISTER:
  95.               begin
  96.                  exprasmlist^.concat(new(pai386,op_reg(A_PUSH,
  97.                    S_L,p^.left^.location.register)));
  98.                  ungetregister32(p^.left^.location.register);
  99.               end;
  100.             LOC_MEM,LOC_REFERENCE:
  101.               begin
  102.                  exprasmlist^.concat(new(pai386,op_ref(A_PUSH,
  103.                    S_L,newreference(p^.left^.location.reference))));
  104.                  del_reference(p^.left^.location.reference);
  105.               end;
  106.             else internalerror(100);
  107.          end;
  108.  
  109.          { generate type checking }
  110.          secondpass(p^.right);
  111.          case p^.right^.location.loc of
  112.             LOC_REGISTER,LOC_CREGISTER:
  113.               begin
  114.                  exprasmlist^.concat(new(pai386,op_reg(A_PUSH,
  115.                    S_L,p^.right^.location.register)));
  116.                  ungetregister32(p^.right^.location.register);
  117.               end;
  118.             LOC_MEM,LOC_REFERENCE:
  119.               begin
  120.                  exprasmlist^.concat(new(pai386,op_ref(A_PUSH,
  121.                    S_L,newreference(p^.right^.location.reference))));
  122.                  del_reference(p^.right^.location.reference);
  123.               end;
  124.             else internalerror(100);
  125.          end;
  126.          emitcall('DO_IS',true);
  127.          exprasmlist^.concat(new(pai386,op_reg_reg(A_OR,S_B,R_AL,R_AL)));
  128.          popusedregisters(pushed);
  129.       end;
  130.  
  131.     procedure setaddresult(cmpop,unsigned : boolean;var p :ptree);
  132.       var
  133.          flags : tresflags;
  134.       begin
  135.          if (p^.left^.resulttype^.deftype<>stringdef) and
  136.             not ((p^.left^.resulttype^.deftype=setdef) and
  137.                (psetdef(p^.left^.resulttype)^.settype<>smallset)) then
  138.            begin
  139.               { this can be useful if for instance length(string) is called }
  140.               if (p^.left^.location.loc=LOC_REFERENCE) or
  141.                  (p^.left^.location.loc=LOC_MEM) then
  142.                 ungetiftemp(p^.left^.location.reference);
  143.               if (p^.right^.location.loc=LOC_REFERENCE) or
  144.                  (p^.right^.location.loc=LOC_MEM) then
  145.                 ungetiftemp(p^.right^.location.reference);
  146.            end;
  147.          { in case of comparison operation the put result in the flags }
  148.          if cmpop then
  149.            begin
  150.               if not(unsigned) then
  151.                 begin
  152.                    if p^.swaped then
  153.                      case p^.treetype of
  154.                         equaln : flags:=F_E;
  155.                         unequaln : flags:=F_NE;
  156.                         ltn : flags:=F_G;
  157.                         lten : flags:=F_GE;
  158.                         gtn : flags:=F_L;
  159.                         gten : flags:=F_LE;
  160.                      end
  161.                    else
  162.                      case p^.treetype of
  163.                         equaln : flags:=F_E;
  164.                         unequaln : flags:=F_NE;
  165.                         ltn : flags:=F_L;
  166.                         lten : flags:=F_LE;
  167.                         gtn : flags:=F_G;
  168.                         gten : flags:=F_GE;
  169.                      end;
  170.                 end
  171.               else
  172.                 begin
  173.                    if p^.swaped then
  174.                      case p^.treetype of
  175.                         equaln : flags:=F_E;
  176.                         unequaln : flags:=F_NE;
  177.                         ltn : flags:=F_A;
  178.                         lten : flags:=F_AE;
  179.                         gtn : flags:=F_B;
  180.                         gten : flags:=F_BE;
  181.                      end
  182.                    else
  183.                      case p^.treetype of
  184.                         equaln : flags:=F_E;
  185.                         unequaln : flags:=F_NE;
  186.                         ltn : flags:=F_B;
  187.                         lten : flags:=F_BE;
  188.                         gtn : flags:=F_A;
  189.                         gten : flags:=F_AE;
  190.                      end;
  191.                 end;
  192.               p^.location.loc:=LOC_FLAGS;
  193.               p^.location.resflags:=flags;
  194.            end;
  195.       end;
  196.  
  197.  
  198.   procedure secondaddstring(var p : ptree);
  199.  
  200.     var
  201.        swapp : ptree;
  202.        pushedregs : tpushed;
  203.        href : treference;
  204.        pushed,cmpop : boolean;
  205.  
  206.     begin
  207.        { string operations are not commutative }
  208.        if p^.swaped then
  209.          begin
  210.             swapp:=p^.left;
  211.             p^.left:=p^.right;
  212.             p^.right:=swapp;
  213.             { because of jump being produced at comparison below: }
  214.             p^.swaped:=not(p^.swaped);
  215.          end;
  216.        case p^.treetype of
  217.           addn :
  218.             begin
  219.                cmpop:=false;
  220.                secondpass(p^.left);
  221.                if (p^.left^.treetype<>addn) then
  222.                  begin
  223.                     { can only reference be }
  224.                     { string in register would be funny    }
  225.                     { therefore produce a temporary string }
  226.  
  227.                     { release the registers }
  228.                     del_reference(p^.left^.location.reference);
  229.                     gettempofsizereference(256,href);
  230.                     copystring(href,p^.left^.location.reference,255);
  231.                     ungetiftemp(p^.left^.location.reference);
  232.  
  233.                     { does not hurt: }
  234.                     p^.left^.location.loc:=LOC_MEM;
  235.                     p^.left^.location.reference:=href;
  236.                  end;
  237.  
  238.                secondpass(p^.right);
  239.  
  240.                { on the right we do not need the register anymore too }
  241.                del_reference(p^.right^.location.reference);
  242. {               if p^.right^.resulttype^.deftype=orddef then
  243.                 begin
  244.                   pushusedregisters(pushedregs,$ff);
  245.                   exprasmlist^.concat(new(pai386,op_ref_reg(
  246.                      A_LEA,S_L,newreference(p^.left^.location.reference),R_EDI)));
  247.                   exprasmlist^.concat(new(pai386,op_reg_reg(
  248.                      A_XOR,S_L,R_EBX,R_EBX)));
  249.                   reset_reference(href);
  250.                   href.base:=R_EDI;
  251.                   exprasmlist^.concat(new(pai386,op_ref_reg(
  252.                      A_MOV,S_B,newreference(href),R_BL)));
  253.                   exprasmlist^.concat(new(pai386,op_reg(
  254.                      A_INC,S_L,R_EBX)));
  255.                   exprasmlist^.concat(new(pai386,op_reg_ref(
  256.                      A_MOV,S_B,R_BL,newreference(href))));
  257.                   href.index:=R_EBX;
  258.                   if p^.right^.treetype=ordconstn then
  259.                     exprasmlist^.concat(new(pai386,op_const_ref(
  260.                        A_MOV,S_L,p^.right^.value,newreference(href))))
  261.                   else
  262.                    begin
  263.                      if p^.right^.location.loc in [LOC_CREGISTER,LOC_REGISTER] then
  264.                       exprasmlist^.concat(new(pai386,op_reg_ref(
  265.                         A_MOV,S_B,p^.right^.location.register,newreference(href))))
  266.                      else
  267.                       begin
  268.                         exprasmlist^.concat(new(pai386,op_ref_reg(
  269.                           A_MOV,S_L,newreference(p^.right^.location.reference),R_EAX)));
  270.                         exprasmlist^.concat(new(pai386,op_reg_ref(
  271.                           A_MOV,S_B,R_AL,newreference(href))));
  272.                       end;
  273.                    end;
  274.                   popusedregisters(pushedregs);
  275.                 end
  276.                else }
  277.                 begin
  278.                   pushusedregisters(pushedregs,$ff);
  279.                   emitpushreferenceaddr(p^.left^.location.reference);
  280.                   emitpushreferenceaddr(p^.right^.location.reference);
  281.                   emitcall('STRCONCAT',true);
  282.                   maybe_loadesi;
  283.                   popusedregisters(pushedregs);
  284.                 end;
  285.  
  286.                set_location(p^.location,p^.left^.location);
  287.                ungetiftemp(p^.right^.location.reference);
  288.             end;
  289.           ltn,lten,gtn,gten,
  290.           equaln,unequaln :
  291.             begin
  292.                cmpop:=true;
  293.              { generate better code for s='' and s<>'' }
  294.                if (p^.treetype in [equaln,unequaln]) and
  295.                   (((p^.left^.treetype=stringconstn) and (p^.left^.values^='')) or
  296.                    ((p^.right^.treetype=stringconstn) and (p^.right^.values^=''))) then
  297.                  begin
  298.                     secondpass(p^.left);
  299.                     { are too few registers free? }
  300.                     pushed:=maybe_push(p^.right^.registers32,p);
  301.                     secondpass(p^.right);
  302.                     if pushed then restore(p);
  303.                     del_reference(p^.right^.location.reference);
  304.                     del_reference(p^.left^.location.reference);
  305.                     { only one node can be stringconstn }
  306.                     { else pass 1 would have evaluted   }
  307.                     { this node                         }
  308.                     if p^.left^.treetype=stringconstn then
  309.                       exprasmlist^.concat(new(pai386,op_const_ref(
  310.                         A_CMP,S_B,0,newreference(p^.right^.location.reference))))
  311.                     else
  312.                       exprasmlist^.concat(new(pai386,op_const_ref(
  313.                         A_CMP,S_B,0,newreference(p^.left^.location.reference))));
  314.                  end
  315.                else
  316.                  begin
  317.                     pushusedregisters(pushedregs,$ff);
  318.                     secondpass(p^.left);
  319.                     del_reference(p^.left^.location.reference);
  320.                     emitpushreferenceaddr(p^.left^.location.reference);
  321.                     secondpass(p^.right);
  322.                     del_reference(p^.right^.location.reference);
  323.                     emitpushreferenceaddr(p^.right^.location.reference);
  324.                     emitcall('STRCMP',true);
  325.                     maybe_loadesi;
  326.                     popusedregisters(pushedregs);
  327.                  end;
  328.                ungetiftemp(p^.left^.location.reference);
  329.                ungetiftemp(p^.right^.location.reference);
  330.             end;
  331.             else Message(sym_e_type_mismatch);
  332.           end;
  333.        setaddresult(cmpop,true,p);
  334.     end;
  335.  
  336.     procedure secondadd(var p : ptree);
  337.  
  338.     { is also being used for xor, and "mul", "sub, or and comparative }
  339.     { operators                                                       }
  340.  
  341.       label do_normal;
  342.  
  343.       var
  344.          swapp : ptree;
  345.          hregister : tregister;
  346.          pushed,mboverflow,cmpop : boolean;
  347.          op : tasmop;
  348.          pushedregs : tpushed;
  349.          flags : tresflags;
  350.          otl,ofl : plabel;
  351.          power : longint;
  352.          href : treference;
  353.          opsize : topsize;
  354.          hl4: plabel;
  355.  
  356.          { true, if unsigned types are compared }
  357.          unsigned : boolean;
  358.  
  359.          { is_in_dest if the result is put directly into }
  360.          { the resulting refernce or varregister }
  361.          { true, if a small set is handled with the longint code }
  362.          is_set : boolean;
  363.          is_in_dest : boolean;
  364.          { true, if for sets subtractions the extra not should generated }
  365.          extra_not : boolean;
  366.  
  367.          mmxbase : tmmxtype;
  368.  
  369.       begin
  370.          if (p^.left^.resulttype^.deftype=stringdef) then
  371.            begin
  372.               secondaddstring(p);
  373.               exit;
  374.            end;
  375.          unsigned:=false;
  376.          is_in_dest:=false;
  377.          extra_not:=false;
  378.  
  379.          opsize:=S_L;
  380.  
  381.          { calculate the operator which is more difficult }
  382.          firstcomplex(p);
  383.          { handling boolean expressions extra: }
  384.          if ((p^.left^.resulttype^.deftype=orddef) and
  385.             (porddef(p^.left^.resulttype)^.typ=bool8bit)) or
  386.             ((p^.right^.resulttype^.deftype=orddef) and
  387.             (porddef(p^.right^.resulttype)^.typ=bool8bit)) then
  388.            begin
  389.               if (p^.treetype=andn) or (p^.treetype=orn) then
  390.                 begin
  391.                    p^.location.loc:=LOC_JUMP;
  392.                    cmpop:=false;
  393.                    case p^.treetype of
  394.                      andn : begin
  395.                                otl:=truelabel;
  396.                                getlabel(truelabel);
  397.                                secondpass(p^.left);
  398.                                maketojumpbool(p^.left);
  399.                                emitl(A_LABEL,truelabel);
  400.                                truelabel:=otl;
  401.                             end;
  402.                      orn : begin
  403.                               ofl:=falselabel;
  404.                               getlabel(falselabel);
  405.                               secondpass(p^.left);
  406.                               maketojumpbool(p^.left);
  407.                               emitl(A_LABEL,falselabel);
  408.                               falselabel:=ofl;
  409.                            end;
  410.                      else Message(sym_e_type_mismatch);
  411.                    end;
  412.                   secondpass(p^.right);
  413.                   maketojumpbool(p^.right);
  414.                 end
  415.               else if p^.treetype in [unequaln,equaln,xorn] then
  416.                 begin
  417.                    opsize:=S_B;
  418.                    if p^.left^.treetype=ordconstn then
  419.                      begin
  420.                         swapp:=p^.right;
  421.                         p^.right:=p^.left;
  422.                         p^.left:=swapp;
  423.                         p^.swaped:=not(p^.swaped);
  424.                      end;
  425.                    secondpass(p^.left);
  426.                    p^.location:=p^.left^.location;
  427.                    { are enough registers free ? }
  428.                    pushed:=maybe_push(p^.right^.registers32,p);
  429.                    secondpass(p^.right);
  430.                    if pushed then restore(p);
  431.                    goto do_normal;
  432.                 end
  433.               else Message(sym_e_type_mismatch);
  434.            end
  435.          else
  436.          if (p^.left^.resulttype^.deftype=setdef) and
  437.             not(psetdef(p^.left^.resulttype)^.settype=smallset) then
  438.            begin
  439.               mboverflow:=false;
  440.               secondpass(p^.left);
  441.               set_location(p^.location,p^.left^.location);
  442.               { are too few registers free? }
  443.               pushed:=maybe_push(p^.right^.registers32,p);
  444.               secondpass(p^.right);
  445.               if pushed then restore(p);
  446.               { not commutative }
  447.               if p^.swaped then
  448.                 begin
  449.                    swapp:=p^.left;
  450.                    p^.left:=p^.right;
  451.                    p^.right:=swapp;
  452.                    { because of jump being produced by comparison }
  453.                    p^.swaped:=not(p^.swaped);
  454.                 end;
  455.               case p^.treetype of
  456.                 equaln,unequaln:
  457.                   begin
  458.                      cmpop:=true;
  459.                      del_reference(p^.left^.location.reference);
  460.                      del_reference(p^.right^.location.reference);
  461.                      pushusedregisters(pushedregs,$ff);
  462.                      emitpushreferenceaddr(p^.right^.location.reference);
  463.                      emitpushreferenceaddr(p^.left^.location.reference);
  464.                      emitcall('SET_COMP_SETS',true);
  465.                      maybe_loadesi;
  466.                      popusedregisters(pushedregs);
  467.                      ungetiftemp(p^.left^.location.reference);
  468.                      ungetiftemp(p^.right^.location.reference);
  469.                   end;
  470.                 addn,symdifn,subn,muln:
  471.                   begin
  472.                      cmpop:=false;
  473.                      del_reference(p^.left^.location.reference);
  474.                      del_reference(p^.right^.location.reference);
  475.                      href.symbol:=nil;
  476.                      pushusedregisters(pushedregs,$ff);
  477.                      gettempofsizereference(32,href);
  478.                      emitpushreferenceaddr(href);
  479.                      { wrong place !! was hard to find out
  480.                      pushusedregisters(pushedregs,$ff);}
  481.                      emitpushreferenceaddr(p^.right^.location.reference);
  482.                      emitpushreferenceaddr(p^.left^.location.reference);
  483.                      case p^.treetype of
  484.                        subn:
  485.                          emitcall('SET_SUB_SETS',true);
  486.                        addn:
  487.                          emitcall('SET_ADD_SETS',true);
  488.                        symdifn:
  489.                          emitcall('SET_SYMDIF_SETS',true);
  490.                        muln:
  491.                          emitcall('SET_MUL_SETS',true);
  492.                      end;
  493.                      maybe_loadesi;
  494.                      popusedregisters(pushedregs);
  495.                      ungetiftemp(p^.left^.location.reference);
  496.                      ungetiftemp(p^.right^.location.reference);
  497.                      p^.location.loc:=LOC_MEM;
  498.                      stringdispose(p^.location.reference.symbol);
  499.                      p^.location.reference:=href;
  500.                   end;
  501.                 else Message(sym_e_type_mismatch);
  502.               end;
  503.            end
  504.          else
  505.            begin
  506.               { in case of constant put it to the left }
  507.               if p^.left^.treetype=ordconstn then
  508.                 begin
  509.                    swapp:=p^.right;
  510.                    p^.right:=p^.left;
  511.                    p^.left:=swapp;
  512.                    p^.swaped:=not(p^.swaped);
  513.                 end;
  514.               secondpass(p^.left);
  515.               { this will be complicated as
  516.                a lot of code below assumes that
  517.                p^.location and p^.left^.location are the same }
  518.  
  519. {$ifdef test_dest_loc}
  520.               if dest_loc_known and (dest_loc_tree=p) and
  521.                  ((dest_loc.loc=LOC_REGISTER) or (dest_loc.loc=LOC_CREGISTER)) then
  522.                 begin
  523.                    set_location(p^.location,dest_loc);
  524.                    in_dest_loc:=true;
  525.                    is_in_dest:=true;
  526.                 end
  527.               else
  528. {$endif test_dest_loc}
  529.                 set_location(p^.location,p^.left^.location);
  530.               { are too few registers free? }
  531.               pushed:=maybe_push(p^.right^.registers32,p);
  532.               secondpass(p^.right);
  533.               if pushed then restore(p);
  534.               if (p^.left^.resulttype^.deftype=pointerdef) or
  535.  
  536.                  (p^.right^.resulttype^.deftype=pointerdef) or
  537.  
  538.                  ((p^.right^.resulttype^.deftype=objectdef) and
  539.                   pobjectdef(p^.right^.resulttype)^.isclass and
  540.                  (p^.left^.resulttype^.deftype=objectdef) and
  541.                   pobjectdef(p^.left^.resulttype)^.isclass
  542.                  ) or
  543.  
  544.                  (p^.left^.resulttype^.deftype=classrefdef) or
  545.  
  546.                  (p^.left^.resulttype^.deftype=procvardef) or
  547.  
  548.                  (p^.left^.resulttype^.deftype=enumdef) or
  549.  
  550.                  ((p^.left^.resulttype^.deftype=orddef) and
  551.                  (porddef(p^.left^.resulttype)^.typ=s32bit)) or
  552.                  ((p^.right^.resulttype^.deftype=orddef) and
  553.                  (porddef(p^.right^.resulttype)^.typ=s32bit)) or
  554.  
  555.                 ((p^.left^.resulttype^.deftype=orddef) and
  556.                  (porddef(p^.left^.resulttype)^.typ=u32bit)) or
  557.                  ((p^.right^.resulttype^.deftype=orddef) and
  558.                  (porddef(p^.right^.resulttype)^.typ=u32bit)) or
  559.  
  560.                 { as well as small sets }
  561.                 ((p^.left^.resulttype^.deftype=setdef) and
  562.                  (psetdef(p^.left^.resulttype)^.settype=smallset)
  563.                 ) then
  564.                 begin
  565.            do_normal:
  566.                    mboverflow:=false;
  567.                    cmpop:=false;
  568.                    if (p^.left^.resulttype^.deftype=pointerdef) or
  569.                       (p^.right^.resulttype^.deftype=pointerdef) or
  570.                       ((p^.left^.resulttype^.deftype=orddef) and
  571.                       (porddef(p^.left^.resulttype)^.typ=u32bit)) or
  572.                       ((p^.right^.resulttype^.deftype=orddef) and
  573.                       (porddef(p^.right^.resulttype)^.typ=u32bit)) then
  574.                      unsigned:=true;
  575.                    is_set:=p^.resulttype^.deftype=setdef;
  576.  
  577.                    case p^.treetype of
  578.                       addn : begin
  579.                                 if is_set then
  580.                                   begin
  581.                                      op:=A_OR;
  582.                                      mboverflow:=false;
  583.                                      unsigned:=false;
  584.                                   end
  585.                                 else
  586.                                   begin
  587.                                      op:=A_ADD;
  588.                                      mboverflow:=true;
  589.                                   end;
  590.                              end;
  591.                       symdifn : begin
  592.                                 { the symetric diff is only for sets }
  593.                                 if is_set then
  594.                                   begin
  595.                                      op:=A_XOR;
  596.                                      mboverflow:=false;
  597.                                      unsigned:=false;
  598.                                   end
  599.                                 else
  600.                                   begin
  601.                                      Message(sym_e_type_mismatch);
  602.                                   end;
  603.                              end;
  604.                       muln : begin
  605.                                 if is_set then
  606.                                   begin
  607.                                      op:=A_AND;
  608.                                      mboverflow:=false;
  609.                                      unsigned:=false;
  610.                                   end
  611.                                 else
  612.                                   begin
  613.                                      if unsigned then
  614.                                        op:=A_MUL
  615.                                      else
  616.                                        op:=A_IMUL;
  617.                                      mboverflow:=true;
  618.                                   end;
  619.                              end;
  620.                       subn : begin
  621.                                 if is_set then
  622.                                   begin
  623.                                      op:=A_AND;
  624.                                      mboverflow:=false;
  625.                                      unsigned:=false;
  626.                                      extra_not:=true;
  627.                                   end
  628.                                 else
  629.                                   begin
  630.                                      op:=A_SUB;
  631.                                      mboverflow:=true;
  632.                                   end;
  633.                              end;
  634.                       ltn,lten,gtn,gten,
  635.                       equaln,unequaln :
  636.                              begin
  637.                                 op:=A_CMP;
  638.                                 cmpop:=true;
  639.                              end;
  640.                       xorn : op:=A_XOR;
  641.                       orn : op:=A_OR;
  642.                       andn : op:=A_AND;
  643.                       else Message(sym_e_type_mismatch);
  644.                    end;
  645.                    { left and right no register?  }
  646.                    { then one must be demanded    }
  647.                    if (p^.left^.location.loc<>LOC_REGISTER) and
  648.                      (p^.right^.location.loc<>LOC_REGISTER) then
  649.                      begin
  650.                         { register variable ? }
  651.                         if (p^.left^.location.loc=LOC_CREGISTER) then
  652.                           begin
  653.                              { it is OK if this is the destination }
  654.                              if is_in_dest then
  655.                                begin
  656.                                   hregister:=p^.location.register;
  657.                                   emit_reg_reg(A_MOV,opsize,p^.left^.location.register,
  658.                                     hregister);
  659.                                end
  660.                              else
  661.                              if cmpop then
  662.                                begin
  663.                                   { do not disturb the register }
  664.                                   hregister:=p^.location.register;
  665.                                end
  666.                              else
  667.                                begin
  668.                                   case opsize of
  669.                                      S_L : hregister:=getregister32;
  670.                                      S_B : hregister:=reg32toreg8(getregister32);
  671.                                   end;
  672.                                   emit_reg_reg(A_MOV,opsize,p^.left^.location.register,
  673.                                     hregister);
  674.                                end
  675.  
  676.                           end
  677.                         else
  678.                           begin
  679.                              del_reference(p^.left^.location.reference);
  680.  
  681.                              if is_in_dest then
  682.                                begin
  683.                                   hregister:=p^.location.register;
  684.                                   exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,opsize,
  685.                                   newreference(p^.left^.location.reference),hregister)));
  686.                                end
  687.                              else
  688.                                begin
  689.                                   { first give free, then demand new register }
  690.                                   case opsize of
  691.                                      S_L : hregister:=getregister32;
  692.                                      S_B : hregister:=reg32toreg8(getregister32);
  693.                                   end;
  694.                                   exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,opsize,
  695.                                     newreference(p^.left^.location.reference),hregister)));
  696.                                end;
  697.                           end;
  698.  
  699.                         p^.location.loc:=LOC_REGISTER;
  700.                         p^.location.register:=hregister;
  701.  
  702.                      end
  703.                    else
  704.                      { if on the right the register then swap }
  705.                      if (p^.right^.location.loc=LOC_REGISTER) then
  706.                        begin
  707.                           swap_location(p^.location,p^.right^.location);
  708.  
  709.                           { newly swapped also set swapped flag }
  710.                           p^.swaped:=not(p^.swaped);
  711.                        end;
  712.                    { at this point, p^.location.loc should be LOC_REGISTER }
  713.                    { and p^.location.register should be a valid register   }
  714.                    { containing the left result                            }
  715.                    if p^.right^.location.loc<>LOC_REGISTER then
  716.                      begin
  717.                         if (p^.treetype=subn) and p^.swaped then
  718.                           begin
  719.                              if p^.right^.location.loc=LOC_CREGISTER then
  720.                                begin
  721.                                   if extra_not then
  722.                                     exprasmlist^.concat(new(pai386,op_reg(A_NOT,opsize,p^.location.register)));
  723.  
  724.                                   emit_reg_reg(A_MOV,opsize,p^.right^.location.register,R_EDI);
  725.                                   emit_reg_reg(op,opsize,p^.location.register,R_EDI);
  726.                                   emit_reg_reg(A_MOV,opsize,R_EDI,p^.location.register);
  727.                                end
  728.                              else
  729.                                begin
  730.                                   if extra_not then
  731.                                     exprasmlist^.concat(new(pai386,op_reg(A_NOT,opsize,p^.location.register)));
  732.  
  733.                                   exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,opsize,
  734.                                     newreference(p^.right^.location.reference),R_EDI)));
  735.                                   exprasmlist^.concat(new(pai386,op_reg_reg(op,opsize,p^.location.register,R_EDI)));
  736.                                   exprasmlist^.concat(new(pai386,op_reg_reg(A_MOV,opsize,R_EDI,p^.location.register)));
  737.                                   del_reference(p^.right^.location.reference);
  738.                                end;
  739.                           end
  740.                         else
  741.                           begin
  742.                              if (p^.right^.treetype=ordconstn) and
  743.                                 (op=A_CMP) and
  744.                                 (p^.right^.value=0) then
  745.                                begin
  746.                                   exprasmlist^.concat(new(pai386,op_reg_reg(A_TEST,opsize,p^.location.register,
  747.                                     p^.location.register)));
  748.                                end
  749.                              else if (p^.right^.treetype=ordconstn) and
  750.                                 (op=A_ADD) and
  751.                                 (p^.right^.value=1) then
  752.                                begin
  753.                                   exprasmlist^.concat(new(pai386,op_reg(A_INC,opsize,
  754.                                     p^.location.register)));
  755.                                end
  756.                              else if (p^.right^.treetype=ordconstn) and
  757.                                 (op=A_SUB) and
  758.                                 (p^.right^.value=1) then
  759.                                begin
  760.                                   exprasmlist^.concat(new(pai386,op_reg(A_DEC,opsize,
  761.                                     p^.location.register)));
  762.                                end
  763.                              else if (p^.right^.treetype=ordconstn) and
  764.                                 (op=A_IMUL) and
  765.                                 (ispowerof2(p^.right^.value,power)) then
  766.                                begin
  767.                                   exprasmlist^.concat(new(pai386,op_const_reg(A_SHL,opsize,power,
  768.                                     p^.location.register)));
  769.                                end
  770.                              else
  771.                                begin
  772.                                   if (p^.right^.location.loc=LOC_CREGISTER) then
  773.                                     begin
  774.                                        if extra_not then
  775.                                          begin
  776.                                             emit_reg_reg(A_MOV,S_L,p^.right^.location.register,R_EDI);
  777.                                             exprasmlist^.concat(new(pai386,op_reg(A_NOT,S_L,R_EDI)));
  778.                                             emit_reg_reg(A_AND,S_L,R_EDI,
  779.                                               p^.location.register);
  780.                                          end
  781.                                        else
  782.                                          begin
  783.                                             emit_reg_reg(op,opsize,p^.right^.location.register,
  784.                                               p^.location.register);
  785.                                          end;
  786.                                     end
  787.                                   else
  788.                                     begin
  789.                                        if extra_not then
  790.                                          begin
  791.                                             exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,newreference(
  792.                                               p^.right^.location.reference),R_EDI)));
  793.                                             exprasmlist^.concat(new(pai386,op_reg(A_NOT,S_L,R_EDI)));
  794.                                             emit_reg_reg(A_AND,S_L,R_EDI,
  795.                                               p^.location.register);
  796.                                          end
  797.                                        else
  798.                                          begin
  799.                                             exprasmlist^.concat(new(pai386,op_ref_reg(op,opsize,newreference(
  800.                                               p^.right^.location.reference),p^.location.register)));
  801.                                          end;
  802.                                        del_reference(p^.right^.location.reference);
  803.                                     end;
  804.                                end;
  805.                           end;
  806.                      end
  807.                    else
  808.                      begin
  809.                         { when swapped another result register }
  810.                         if (p^.treetype=subn) and p^.swaped then
  811.                           begin
  812.                              if extra_not then
  813.                                exprasmlist^.concat(new(pai386,op_reg(A_NOT,S_L,p^.location.register)));
  814.  
  815.                              exprasmlist^.concat(new(pai386,op_reg_reg(op,opsize,
  816.                                p^.location.register,p^.right^.location.register)));
  817.                                swap_location(p^.location,p^.right^.location);
  818.                                { newly swapped also set swapped flag }
  819.                                { just to maintain ordering           }
  820.                                p^.swaped:=not(p^.swaped);
  821.                           end
  822.                         else
  823.                           begin
  824.                              if extra_not then
  825.                                exprasmlist^.concat(new(pai386,op_reg(A_NOT,S_L,p^.right^.location.register)));
  826.                              exprasmlist^.concat(new(pai386,op_reg_reg(op,opsize,
  827.                                p^.right^.location.register,
  828.                                p^.location.register)));
  829.                           end;
  830.                         case opsize of
  831.                            S_L : ungetregister32(p^.right^.location.register);
  832.                            S_B : ungetregister32(reg8toreg32(p^.right^.location.register));
  833.                         end;
  834.                      end;
  835.  
  836.                    if cmpop then
  837.                      case opsize of
  838.                         S_L : ungetregister32(p^.location.register);
  839.                         S_B : ungetregister32(reg8toreg32(p^.location.register));
  840.                      end;
  841.  
  842.                    { only in case of overflow operations }
  843.                    { produce overflow code }
  844.                    if mboverflow then
  845.                    { we must put it here directly, because sign of operation }
  846.                    { is in unsigned VAR!!                                    }
  847.                    begin
  848.                      if cs_check_overflow in aktswitches  then
  849.                      begin
  850.                        getlabel(hl4);
  851.                        if unsigned then
  852.                         emitl(A_JNB,hl4)
  853.                        else
  854.                         emitl(A_JNO,hl4);
  855.                        emitcall('RE_OVERFLOW',true);
  856.                        emitl(A_LABEL,hl4);
  857.                      end;
  858.                    end;
  859.                 end
  860.               else if ((p^.left^.resulttype^.deftype=orddef) and
  861.                  (porddef(p^.left^.resulttype)^.typ=uchar)) then
  862.                 begin
  863.                    case p^.treetype of
  864.                       ltn,lten,gtn,gten,
  865.                       equaln,unequaln :
  866.                                 cmpop:=true;
  867.                       else Message(sym_e_type_mismatch);
  868.                    end;
  869.                    unsigned:=true;
  870.                    { left and right no register? }
  871.                    { the one must be demanded    }
  872.                    if (p^.location.loc<>LOC_REGISTER) and
  873.                      (p^.right^.location.loc<>LOC_REGISTER) then
  874.                      begin
  875.                         if p^.location.loc=LOC_CREGISTER then
  876.                           begin
  877.                              if cmpop then
  878.                                { do not disturb register }
  879.                                hregister:=p^.location.register
  880.                              else
  881.                                begin
  882.                                   hregister:=reg32toreg8(getregister32);
  883.                                   emit_reg_reg(A_MOV,S_B,p^.location.register,
  884.                                     hregister);
  885.                                end;
  886.                           end
  887.                         else
  888.                           begin
  889.                              del_reference(p^.location.reference);
  890.  
  891.                              { first give free then demand new register }
  892.                              hregister:=reg32toreg8(getregister32);
  893.                              exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_B,newreference(p^.location.reference),
  894.                                hregister)));
  895.                           end;
  896.                         p^.location.loc:=LOC_REGISTER;
  897.                         p^.location.register:=hregister;
  898.                      end;
  899.  
  900.                    { now p always a register }
  901.  
  902.                    if (p^.right^.location.loc=LOC_REGISTER) and
  903.                       (p^.location.loc<>LOC_REGISTER) then
  904.                      begin
  905.                        swap_location(p^.location,p^.right^.location);
  906.  
  907.                         { newly swapped also set swapped flag }
  908.                         p^.swaped:=not(p^.swaped);
  909.                      end;
  910.                    if p^.right^.location.loc<>LOC_REGISTER then
  911.                      begin
  912.                         if p^.right^.location.loc=LOC_CREGISTER then
  913.                           begin
  914.                              emit_reg_reg(A_CMP,S_B,
  915.                                 p^.right^.location.register,p^.location.register);
  916.                           end
  917.                         else
  918.                           begin
  919.                              exprasmlist^.concat(new(pai386,op_ref_reg(A_CMP,S_B,newreference(
  920.                                 p^.right^.location.reference),p^.location.register)));
  921.                              del_reference(p^.right^.location.reference);
  922.                           end;
  923.                      end
  924.                    else
  925.                      begin
  926.                         emit_reg_reg(A_CMP,S_B,p^.right^.location.register,
  927.                           p^.location.register);
  928.                         ungetregister32(reg8toreg32(p^.right^.location.register));
  929.                      end;
  930.                    ungetregister32(reg8toreg32(p^.location.register));
  931.                 end
  932.               else if (p^.left^.resulttype^.deftype=floatdef) and
  933.                   (pfloatdef(p^.left^.resulttype)^.typ<>f32bit) then
  934.                  begin
  935.                     { real constants to the left }
  936.                     if p^.left^.treetype=realconstn then
  937.                       begin
  938.                          swapp:=p^.right;
  939.                          p^.right:=p^.left;
  940.                          p^.left:=swapp;
  941.                          p^.swaped:=not(p^.swaped);
  942.                       end;
  943.                     cmpop:=false;
  944.                     case p^.treetype of
  945.                        addn : op:=A_FADDP;
  946.                        muln : op:=A_FMULP;
  947.                        subn : op:=A_FSUBP;
  948.                        slashn : op:=A_FDIVP;
  949.                        ltn,lten,gtn,gten,
  950.                        equaln,unequaln : begin
  951.                                             op:=A_FCOMPP;
  952.                                             cmpop:=true;
  953.                                          end;
  954.                        else Message(sym_e_type_mismatch);
  955.                     end;
  956.  
  957.                     if (p^.right^.location.loc<>LOC_FPU) then
  958.                       begin
  959.                          floatload(pfloatdef(p^.right^.resulttype)^.typ,p^.right^.location.reference);
  960.                          if (p^.left^.location.loc<>LOC_FPU) then
  961.                            floatload(pfloatdef(p^.left^.resulttype)^.typ,p^.left^.location.reference)
  962.                          { left was on the stack => swap }
  963.                          else
  964.                            p^.swaped:=not(p^.swaped);
  965.  
  966.                          { releases the right reference }
  967.                          del_reference(p^.right^.location.reference);
  968.                       end
  969.                     { the nominator in st0 }
  970.                     else if (p^.left^.location.loc<>LOC_FPU) then
  971.                       floatload(pfloatdef(p^.left^.resulttype)^.typ,p^.left^.location.reference)
  972.                     { fpu operands are always in the wrong order on the stack }
  973.                     else
  974.                       p^.swaped:=not(p^.swaped);
  975.  
  976.                     { releases the left reference }
  977.                     if (p^.left^.location.loc<>LOC_FPU) then
  978.                       del_reference(p^.left^.location.reference);
  979.  
  980.                     { if we swaped the tree nodes, then use the reverse operator }
  981.                     if p^.swaped then
  982.                       begin
  983.                          if (p^.treetype=slashn) then
  984.                            op:=A_FDIVRP
  985.                          else if (p^.treetype=subn) then
  986.                            op:=A_FSUBRP;
  987.                       end;
  988.                     { to avoid the pentium bug
  989.                     if (op=FDIVP) and (opt_processors=pentium) then
  990.                       exprasmlist^.concat(new(pai386,op_CALL,S_NO,'EMUL_FDIVP')
  991.                     else
  992.                     }
  993.                     { the Intel assemblers want operands }
  994.                     if op<>A_FCOMPP then
  995.                        exprasmlist^.concat(new(pai386,op_reg_reg(op,S_NO,R_ST,R_ST1)))
  996.                     else
  997.                       exprasmlist^.concat(new(pai386,op_none(op,S_NO)));
  998.                     { on comparison load flags }
  999.                     if cmpop then
  1000.                       begin
  1001.                          if not(R_EAX in unused) then
  1002.                            emit_reg_reg(A_MOV,S_L,R_EAX,R_EDI);
  1003.                          exprasmlist^.concat(new(pai386,op_reg(A_FNSTSW,S_NO,R_AX)));
  1004.                          exprasmlist^.concat(new(pai386,op_none(A_SAHF,S_NO)));
  1005.                          if not(R_EAX in unused) then
  1006.                            emit_reg_reg(A_MOV,S_L,R_EDI,R_EAX);
  1007.                          if p^.swaped then
  1008.                            case p^.treetype of
  1009.                               equaln : flags:=F_E;
  1010.                               unequaln : flags:=F_NE;
  1011.                               ltn : flags:=F_A;
  1012.                               lten : flags:=F_AE;
  1013.                               gtn : flags:=F_B;
  1014.                               gten : flags:=F_BE;
  1015.                            end
  1016.                          else
  1017.                            case p^.treetype of
  1018.                               equaln : flags:=F_E;
  1019.                               unequaln : flags:=F_NE;
  1020.                               ltn : flags:=F_B;
  1021.                               lten : flags:=F_BE;
  1022.                               gtn : flags:=F_A;
  1023.                               gten : flags:=F_AE;
  1024.                            end;
  1025.                          p^.location.loc:=LOC_FLAGS;
  1026.                          p^.location.resflags:=flags;
  1027.                          cmpop:=false;
  1028.                       end
  1029.                     else
  1030.                       p^.location.loc:=LOC_FPU;
  1031.                  end
  1032. {$ifdef SUPPORT_MMX}
  1033.                else if is_mmx_able_array(p^.left^.resulttype) then
  1034.                  begin
  1035.                    cmpop:=false;
  1036.                    mmxbase:=mmx_type(p^.left^.resulttype);
  1037.                    case p^.treetype of
  1038.                       addn : begin
  1039.                                 if (cs_mmx_saturation in aktswitches^) then
  1040.                                   begin
  1041.                                      case mmxbase of
  1042.                                         mmxs8bit:
  1043.                                           op:=A_PADDSB;
  1044.                                         mmxu8bit:
  1045.                                           op:=A_PADDUSB;
  1046.                                         mmxs16bit,mmxfixed16:
  1047.                                           op:=A_PADDSB;
  1048.                                         mmxu16bit:
  1049.                                           op:=A_PADDUSW;
  1050.                                      end;
  1051.                                   end
  1052.                                 else
  1053.                                   begin
  1054.                                      case mmxbase of
  1055.                                         mmxs8bit,mmxu8bit:
  1056.                                           op:=A_PADDB;
  1057.                                         mmxs16bit,mmxu16bit,mmxfixed16:
  1058.                                           op:=A_PADDW;
  1059.                                         mmxs32bit,mmxu32bit:
  1060.                                           op:=A_PADDD;
  1061.                                      end;
  1062.                                   end;
  1063.                              end;
  1064.                       muln : begin
  1065.                                 case mmxbase of
  1066.                                    mmxs16bit,mmxu16bit:
  1067.                                      op:=A_PMULLW;
  1068.                                    mmxfixed16:
  1069.                                      op:=A_PMULHW;
  1070.                                 end;
  1071.                              end;
  1072.                       subn : begin
  1073.                                 if (cs_mmx_saturation in aktswitches^) then
  1074.                                   begin
  1075.                                      case mmxbase of
  1076.                                         mmxs8bit:
  1077.                                           op:=A_PSUBSB;
  1078.                                         mmxu8bit:
  1079.                                           op:=A_PSUBUSB;
  1080.                                         mmxs16bit,mmxfixed16:
  1081.                                           op:=A_PSUBSB;
  1082.                                         mmxu16bit:
  1083.                                           op:=A_PSUBUSW;
  1084.                                      end;
  1085.                                   end
  1086.                                 else
  1087.                                   begin
  1088.                                      case mmxbase of
  1089.                                         mmxs8bit,mmxu8bit:
  1090.                                           op:=A_PSUBB;
  1091.                                         mmxs16bit,mmxu16bit,mmxfixed16:
  1092.                                           op:=A_PSUBW;
  1093.                                         mmxs32bit,mmxu32bit:
  1094.                                           op:=A_PSUBD;
  1095.                                      end;
  1096.                                   end;
  1097.                              end;
  1098.                       {
  1099.                       ltn,lten,gtn,gten,
  1100.                       equaln,unequaln :
  1101.                              begin
  1102.                                 op:=A_CMP;
  1103.                                 cmpop:=true;
  1104.                              end;
  1105.                       }
  1106.                       xorn:
  1107.                         op:=A_PXOR;
  1108.                       orn:
  1109.                         op:=A_POR;
  1110.                       andn:
  1111.                         op:=A_PAND;
  1112.                       else Message(sym_e_type_mismatch);
  1113.                    end;
  1114.                    { left and right no register?  }
  1115.                    { then one must be demanded    }
  1116.                    if (p^.left^.location.loc<>LOC_MMXREGISTER) and
  1117.                      (p^.right^.location.loc<>LOC_MMXREGISTER) then
  1118.                      begin
  1119.                         { register variable ? }
  1120.                         if (p^.left^.location.loc=LOC_CMMXREGISTER) then
  1121.                           begin
  1122.                              { it is OK if this is the destination }
  1123.                              if is_in_dest then
  1124.                                begin
  1125.                                   hregister:=p^.location.register;
  1126.                                   emit_reg_reg(A_MOVQ,S_NO,p^.left^.location.register,
  1127.                                     hregister);
  1128.                                end
  1129.                              else
  1130.                                begin
  1131.                                   hregister:=getregistermmx;
  1132.                                   emit_reg_reg(A_MOVQ,S_NO,p^.left^.location.register,
  1133.                                     hregister);
  1134.                                end
  1135.  
  1136.                           end
  1137.                         else
  1138.                           begin
  1139.                              del_reference(p^.left^.location.reference);
  1140.  
  1141.                              if is_in_dest then
  1142.                                begin
  1143.                                   hregister:=p^.location.register;
  1144.                                   exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVQ,S_NO,
  1145.                                   newreference(p^.left^.location.reference),hregister)));
  1146.                                end
  1147.                              else
  1148.                                begin
  1149.                                   hregister:=getregistermmx;
  1150.                                   exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVQ,S_NO,
  1151.                                     newreference(p^.left^.location.reference),hregister)));
  1152.                                end;
  1153.                           end;
  1154.  
  1155.                         p^.location.loc:=LOC_MMXREGISTER;
  1156.                         p^.location.register:=hregister;
  1157.  
  1158.                      end
  1159.                    else
  1160.                      { if on the right the register then swap }
  1161.                      if (p^.right^.location.loc=LOC_MMXREGISTER) then
  1162.                        begin
  1163.                           swap_location(p^.location,p^.right^.location);
  1164.  
  1165.                           { newly swapped also set swapped flag }
  1166.                           p^.swaped:=not(p^.swaped);
  1167.                        end;
  1168.                    { at this point, p^.location.loc should be LOC_MMXREGISTER }
  1169.                    { and p^.location.register should be a valid register      }
  1170.                    { containing the left result                               }
  1171.                    if p^.right^.location.loc<>LOC_MMXREGISTER then
  1172.                      begin
  1173.                         if (p^.treetype=subn) and p^.swaped then
  1174.                           begin
  1175.                              if p^.right^.location.loc=LOC_CMMXREGISTER then
  1176.                                begin
  1177.                                   emit_reg_reg(A_MOVQ,S_NO,p^.right^.location.register,R_MM7);
  1178.                                   emit_reg_reg(op,S_NO,p^.location.register,R_EDI);
  1179.                                   emit_reg_reg(A_MOVQ,S_NO,R_MM7,p^.location.register);
  1180.                                end
  1181.                              else
  1182.                                begin
  1183.  
  1184.                                   exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVQ,S_NO,
  1185.                                     newreference(p^.right^.location.reference),R_MM7)));
  1186.                                   exprasmlist^.concat(new(pai386,op_reg_reg(op,S_NO,p^.location.register,
  1187.                                     R_MM7)));
  1188.                                   exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVQ,S_NO,
  1189.                                     R_MM7,p^.location.register)));
  1190.                                   del_reference(p^.right^.location.reference);
  1191.                                end;
  1192.                           end
  1193.                         else
  1194.                           begin
  1195.                              if (p^.right^.location.loc=LOC_CREGISTER) then
  1196.                                begin
  1197.                                   emit_reg_reg(op,S_NO,p^.right^.location.register,
  1198.                                     p^.location.register);
  1199.                                end
  1200.                              else
  1201.                                begin
  1202.                                   exprasmlist^.concat(new(pai386,op_ref_reg(op,S_NO,newreference(
  1203.                                     p^.right^.location.reference),p^.location.register)));
  1204.                                   del_reference(p^.right^.location.reference);
  1205.                                end;
  1206.                           end;
  1207.                      end
  1208.                    else
  1209.                      begin
  1210.                         { when swapped another result register }
  1211.                         if (p^.treetype=subn) and p^.swaped then
  1212.                           begin
  1213.                              exprasmlist^.concat(new(pai386,op_reg_reg(op,S_NO,
  1214.                                p^.location.register,p^.right^.location.register)));
  1215.                                swap_location(p^.location,p^.right^.location);
  1216.                                { newly swapped also set swapped flag }
  1217.                                { just to maintain ordering           }
  1218.                                p^.swaped:=not(p^.swaped);
  1219.                           end
  1220.                         else
  1221.                           begin
  1222.                              exprasmlist^.concat(new(pai386,op_reg_reg(op,S_NO,
  1223.                                p^.right^.location.register,
  1224.                                p^.location.register)));
  1225.                           end;
  1226.                         ungetregistermmx(p^.right^.location.register);
  1227.                      end;
  1228.                 end
  1229. {$endif SUPPORT_MMX}
  1230.               else Message(sym_e_type_mismatch);
  1231.            end;
  1232.        setaddresult(cmpop,unsigned,p);
  1233.     end;
  1234.  
  1235. {
  1236.      $Log: cgi386ad.inc,v $
  1237.      Revision 1.2.2.1  1998/04/08 11:38:43  peter
  1238.        * nasm patches, pierres symtable patch
  1239.  
  1240.      Revision 1.2  1998/03/28 23:09:55  florian
  1241.        * secondin bugfix (m68k and i386)
  1242.        * overflow checking bugfix (m68k and i386) -- pretty useless in
  1243.          secondadd, since everything is done using 32-bit
  1244.        * loading pointer to routines hopefully fixed (m68k)
  1245.        * flags problem with calls to RTL internal routines fixed (still strcmp
  1246.          to fix) (m68k)
  1247.        * #ELSE was still incorrect (didn't take care of the previous level)
  1248.        * problem with filenames in the command line solved
  1249.        * problem with mangledname solved
  1250.        * linking name problem solved (was case insensitive)
  1251.        * double id problem and potential crash solved
  1252.        * stop after first error
  1253.        * and=>test problem removed
  1254.        * correct read for all float types
  1255.        * 2 sigsegv fixes and a cosmetic fix for Internal Error
  1256.        * push/pop is now correct optimized (=> mov (%esp),reg)
  1257.  
  1258.      Revision 1.1.1.1  1998/03/25 11:18:12  root
  1259.      * Restored version
  1260.  
  1261.      Revision 1.15  1998/03/10 23:48:36  florian
  1262.        * a couple of bug fixes to get the compiler with -OGaxz compiler, sadly
  1263.          enough, it doesn't run
  1264.  
  1265.      Revision 1.14  1998/03/10 01:17:18  peter
  1266.        * all files have the same header
  1267.        * messages are fully implemented, EXTDEBUG uses Comment()
  1268.        + AG... files for the Assembler generation
  1269.  
  1270.      Revision 1.13  1998/03/09 10:44:38  peter
  1271.        + string='', string<>'', string:='', string:=char optimizes (the first 2
  1272.          were already in cg68k2)
  1273.  
  1274.      Revision 1.12  1998/03/06 00:52:16  peter
  1275.        * replaced all old messages from errore.msg, only ExtDebug and some
  1276.          Comment() calls are left
  1277.        * fixed options.pas
  1278.  
  1279.      Revision 1.11  1998/03/02 01:48:30  peter
  1280.        * renamed target_DOS to target_GO32V1
  1281.        + new verbose system, merged old errors and verbose units into one new
  1282.          verbose.pas, so errors.pas is obsolete
  1283.  
  1284.      Revision 1.10  1998/02/15 21:27:50  florian
  1285.      *** empty log message ***
  1286. }
  1287.